package com.ruoyi.common.security.utils;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.api.domain.SysDictData;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 字典工具类
 *
 * @author ruoyi
 */
public class DictUtils
{
    /**
     * 设置字典缓存
     *
     * @param key 参数键
     * @param dictDatas 字典数据列表
     */
    public static void setDictCache(String key, List<SysDictData> dictDatas)
    {
        SpringUtils.getBean(RedisService.class).setCacheObject(getCacheKey(key), dictDatas);
    }

    /**
     * 获取字典缓存
     *
     * @param key 参数键
     * @return dictDatas 字典数据列表
     */
    public static List<SysDictData> getDictCache(String key)
    {
        JSONArray arrayCache = SpringUtils.getBean(RedisService.class).getCacheObject(getCacheKey(key));
        if (StringUtils.isNotNull(arrayCache))
        {
            return arrayCache.toList(SysDictData.class);
        }
        return null;
    }

    /**
     * 删除指定字典缓存
     *
     * @param key 字典键
     */
    public static void removeDictCache(String key)
    {
        SpringUtils.getBean(RedisService.class).deleteObject(getCacheKey(key));
    }

    /**
     * 清空字典缓存
     */
    public static void clearDictCache()
    {
        Collection<String> keys = SpringUtils.getBean(RedisService.class).keys(CacheConstants.SYS_DICT_KEY + "*");
        SpringUtils.getBean(RedisService.class).deleteObject(keys);
    }

    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    public static String getCacheKey(String configKey)
    {
        return CacheConstants.SYS_DICT_KEY + configKey;
    }


    /**
     * 根据指定的type ，value 获取 label
     * @param value
     * @param dictType
     * @return
     * @throws Exception
     */
    public static String getDictLabelByTypeAndValue(String value,String dictType) throws Exception {
        String label = value;
        try {
            label = DictUtils.getDictLabelByTypeAndValue(value, dictType, value);
        } catch (Exception e) {
            throw e;
        }
        return label;
    }

    /**
     *  根据type,label 获取value
     * @param propertyLabel
     * @param dictType
     * @return
     * @throws Exception
     */
    public static Long getDictValueByTypeAndLabel(String propertyLabel, String dictType) throws Exception{
        Long value =  null;
        try {
            value = DictUtils.getDictValueByTypeAndLabel(propertyLabel, dictType, propertyLabel);
        } catch (Exception e) {
            throw e;
        }
        return value;
    }

    /**
     *  根据type,名称 获取id
     * @param
     * @param classType
     * @return
     * @throws Exception
     */
    public static Long getClassIdByTypeAndName(String propertyLabel, String classType) throws Exception{
        Long value =  null;
        try {
            // 通过反射获取类
            Class clz = Class.forName(classType);
            Object bean = SpringUtils.getBean(clz);
            Method getIdByName = clz.getMethod("getOne", Wrapper.class);
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("name",propertyLabel);
            Object invoke = getIdByName.invoke(bean, wrapper);
            Class<?> aClass = invoke.getClass();
            Method method = aClass.getMethod("getId");
            value = (Long) method.invoke(invoke);

        } catch (Exception e) {
            throw e;
        }
        return value;
    }

    /**
     *  通过反射获取单元格的值
     * @param valueOf id
     * @param classType 类的路径
     * @return
     */
    private String getDictNameAndValue(Long valueOf, String classType) throws Exception {
        // 通过反射获取类
        Class clz = Class.forName(classType);
        Object bean = SpringUtils.getBean(clz);
        Method getIdByName = clz.getMethod("getById", Serializable.class);
        Object invoke = getIdByName.invoke(bean, valueOf);
        Class<?> aClass = invoke.getClass();
        Method method = aClass.getMethod("getName");
        String value = (String) method.invoke(invoke);
        return value;
    }

    /**
     * 根据类的路径获取名称
     * @param classType
     * @return
     * @throws Exception
     */
    private String[] getClassLabelArr(String classType){

        List<Object> objects = null;
        try {
            // 获取反射的class
            Class clz = Class.forName(classType);
            // 从启动类中得到bean;spring工具类 方便在非spring管理环境中获取bean
            Object bean = SpringUtils.getBean(clz);
            Method listMethod = clz.getMethod("list");
            // 通过反射获取方法,方法调用得到一个list(因为调用list方法得到的一定是list)
            objects = (List<Object>) listMethod.invoke(bean);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 数组长度即使集合的长度
        List<String> result = new ArrayList<>();
        // 遍历数组得到名称label,如果数据多的话。性能低，需优化
        objects.forEach(obj -> {
            Class<?> aClass = obj.getClass();
            try {
                Method method = aClass.getMethod("getName");
                String value = (String) method.invoke(obj);
                result.add(value);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 把String集合转成String数组返回出去
        return result.toArray(new String[result.size()]);
    }

    /**
     * 根据指定的type ，value 获取 label
     * @param value
     * @param type
     * @param defaultLabel 默认label
     * @return
     */
    public static String getDictLabelByTypeAndValue(String value, String type, String defaultLabel){
        if (StringUtils.isNotBlank(type) && ObjectUtils.isNotNull(value)){
            List<SysDictData> dataList = getDictCache(type);
            for (SysDictData dict : dataList){
                if (type.equals(dict.getDictType()) && value.equals(dict.getDictCode().toString())){
                    return dict.getDictLabel();
                }
            }
        }
        return defaultLabel;
    }

    /**
     * 根据type,label 获取value
     *
     * @param label
     * @param type
     * @param defaultValue
     * @return
     */
    public static Long getDictValueByTypeAndLabel(String label,String type,String defaultValue) {
        if (StringUtils.isNotBlank(type) && StringUtils.isNotBlank(label)){
            for (SysDictData dict : getDictCache(type)){
                if(type.equals(dict.getDictType())  && label.equals(dict.getDictLabel())) {
                    return dict.getDictCode();
                }
            }
        }
        return null;
    }

    /**
     * 根据 type 将 lable组成 string数组
     * @param type
     * @return
     */
    public static String[] getLabelArr(String type) {
        String[] arr0 = new String[0];
        if (StringUtils.isNotBlank(type)) {
            List<SysDictData> dictList = getDictCache(type);
            String[] strArr = new String[dictList.size()];
            for (int i = 0 ; i < dictList.size() ; i ++) {
                strArr[i] = dictList.get(i).getDictLabel();
            }
            return strArr;
        }
        return arr0;
    }
}
